import java.lang.reflect.*;
import java.lang.annotation.*;

interface Moveable {
    void move();
    void stop();
}

class Tank implements Moveable {
    @Override
    @MethodProxy
    public void move() {
        System.out.println("Tank Moving...!");
    }
    @Override
    public void stop() {
        System.out.println("Tank Stop...!");
    }
}

class ProxyHandler implements InvocationHandler {
    Object o;
    Method [] methods;
    Object run;

    public ProxyHandler(Object o, Object run) {
        this.o = o;
        this.run = run;
        methods = o.getClass().getMethods();
    }

    public boolean isAnnotation(Method method, Class<? extends Annotation> c) {
        Annotation a = null;

        for (Method m : this.methods) {
            if (equalsMethod(m, method)) {
                a = m.getAnnotation(c);
                break;
            }
        }
        return (a == null) ? false : true;
    }

    public boolean equalsMethod(Method m1, Method m2) {
        //方法名相同
        //形参个数相同
        //形参类型是否匹配
        //抛出异常个数
        //抛出异常类型
        //返回值
        return m1.getName().equals(m2.getName());
    }

    public void invokeAnnotation(Class<? extends Annotation> annotation) throws Exception {
        for (Method m : run.getClass().getDeclaredMethods()) {
            if (m.getAnnotation(annotation) != null) {
                m.invoke(run);
            }
        }
    }

    public Object invoke(Object proxy, Method m, Object [] args) throws Throwable {
        boolean flags = isAnnotation(m, MethodProxy.class);

        if (flags) {
            invokeAnnotation(Before.class);
        }

        Object r = m.invoke(o, args);

        if (flags) {
            invokeAnnotation(After.class);
        }

        return r;
    }
}

class DynamicProxy {
    public static <T> T getInstance(Class<T> c, ProxyHandler proxy) {
        return (T)Proxy.newProxyInstance(c.getClassLoader(),
                                            new Class<?>[]{c}, proxy);
    }
}

public class DynamicProxyV2 {
    static public void main(String [] args) throws Exception {
        Tank tank = new Tank();
        tank.move();

        System.out.printf("==============\n");

        Moveable p = DynamicProxy.getInstance(Moveable.class,
                            new ProxyHandler(tank, new Object() {

            @Before
            public void abc() {
                System.out.printf("Kyo Before1....\n");
            }

            @Before
            public void abc1() {
                System.out.printf("Kyo Before2....\n");
            }

            @After
            public void jfklsdjf() {
                System.out.printf("Kyo After....\n");
            }
                            }));
        p.move();
        p.stop();
    }
}
